package cn.t.facade.device;


import cn.t.constants.ResponseError;
import cn.t.converter.device.CargowaySkuDTOConverter;
import cn.t.core.exception.BizException;
import cn.t.core.facade.FacadeImpl;
import cn.t.dto.android.AndroidCargowayDTO;
import cn.t.dto.api.CustomerItemDTO;
import cn.t.dto.device.CargowaySkuDTO;
import cn.t.dto.device.UserRoleSkuDTO;
import cn.t.dto.device.vo.OpenCloseDTO;
import cn.t.dto.device.vo.QtyVO;
import cn.t.dto.device.vo.WeightVO;
import cn.t.enums.PickStatusEnum;
import cn.t.enums.order.ErrorEnum;
import cn.t.facade.sku.SkuFacade;
import cn.t.model.device.CargowayDO;
import cn.t.model.device.CargowaySkuDO;
import cn.t.model.device.DeviceDO;
import cn.t.model.sku.SkuDO;
import cn.t.service.device.CargowayService;
import cn.t.service.device.CargowaySkuService;
import cn.t.service.device.DeviceService;
import cn.t.service.sku.SkuService;
import cn.t.service.user.CustomerFirmService;
import cn.t.vo.andriod.AndroidCargowayVO;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 货道商品表(CargowaySku)服务编排
 *
 * @author t
 * @since 2024-05-24 10:19:33
 */
@Slf4j
@Service
@AllArgsConstructor
public class CargowaySkuFacade extends FacadeImpl<CargowaySkuDTO, CargowaySkuDO, CargowaySkuDTOConverter, CargowaySkuService> {
    @Resource
    private CargowayService cargowayService;
    @Resource
    private SkuService skuService;
    @Resource
    private DeviceService deviceService;

    private final SkuFacade skuFacade;
    private final CustomerFirmService customerFirmService;

    public Map<Integer, CargowaySkuDTO> cargowayMap(Long deviceId) {
        return findByDeviceId(deviceId).stream().collect(Collectors.toMap(CargowaySkuDTO::getCargowayNo, cargowaySkuDTO -> cargowaySkuDTO));
    }

    public List<CargowaySkuDTO> findByDeviceId(Long deviceId) {
        if (deviceId == null) {
            throw new BizException(ResponseError.PARAM_NOT_FOUND, String.format(ResponseError.PARAM_NOT_FOUND.getName(), "deviceId"));
        }
        CargowaySkuDO template = new CargowaySkuDO();
        template.setDeviceId(deviceId);
        List<CargowaySkuDO> byModel = service.findByModel(template, 0, Integer.MAX_VALUE, null, null);
        List<String> skus = byModel.stream().map(CargowaySkuDO::getSkuCode).collect(Collectors.toList());

        //数据填充
        Map<String, SkuDO> skuMap = skuService.findModelList(skus).stream().collect(Collectors.toMap(SkuDO::getSkuCode, skuDO -> skuDO));
        // 设备货道
        Map<Long, CargowayDO> cargowayList = cargowayService.getCargowayList(Collections.singletonList(deviceId)).stream().collect(Collectors.toMap(CargowayDO::getId, cargowayDO -> cargowayDO));

        return byModel.stream().map(cargowaySkuDO -> {
            CargowaySkuDTO cargowaySkuDTO = converter.model2Dto(cargowaySkuDO);
            SkuDO skuDO = skuMap.get(cargowaySkuDO.getSkuCode());
            if (skuDO != null) {
                cargowaySkuDTO.setErrorRate(skuDO.getErrorRate());
                cargowaySkuDTO.setSkuWeight(skuDO.getWeight());
                cargowaySkuDTO.setCategoryName(skuDO.getCategoryName());
                cargowaySkuDTO.setCategoryId(skuDO.getCategoryId());
                cargowaySkuDTO.setSkuImg(skuDO.getSkuImg());
            } else {
                throw new BizException(ErrorEnum.SKU_NOT_FOUND, String.format(ErrorEnum.SKU_NOT_FOUND.getMessage(), cargowaySkuDO.getSkuCode()));
            }

            if (cargowayList.get(cargowaySkuDO.getCargowayId()) != null) {
                cargowaySkuDTO.setCargowayNo(cargowayList.get(cargowaySkuDO.getCargowayId()).getCargowayNo());
            } else {
                throw new BizException(ErrorEnum.CARGOWAY_CODE_NOT_FOUND, String.format(ErrorEnum.CARGOWAY_CODE_NOT_FOUND.getMessage(), cargowaySkuDO.getCargowayId()));
            }

            return cargowaySkuDTO;
        }).collect(Collectors.toList());
    }

    public Boolean batchUpdate(List<CargowaySkuDTO> cargowaySkuList) {
        log.info("批量更新货道商品信息 {}", cargowaySkuList);
        return service.updateBatch(converter.dtoList2DoList(cargowaySkuList));
    }

    public void updateByOpenCloseData(OpenCloseDTO openCloseWeightVO) {
        if (ObjectUtils.isEmpty(openCloseWeightVO.getQtyList())) {
            openCloseWeightVO.setQtyList(new ArrayList<>());
        }
        //过滤掉异常数量信息
        Map<Integer, QtyVO> qtyMap = openCloseWeightVO.getQtyList().stream().filter(qtyVO -> qtyVO.getErrorTypeEnum() == null).collect(Collectors.toMap(QtyVO::getNo, Function.identity()));
        //关门数据
        Map<Integer, WeightVO> weightMap = openCloseWeightVO.getScale().stream().collect(Collectors.toMap(WeightVO::getNo, Function.identity()));
        //货道商品信息
        List<CargowaySkuDTO> cargowaySkuList = new ArrayList<>(openCloseWeightVO.getCargowaySkuMap().values());


        //更新上架货道信息
        List<CargowaySkuDTO> cargowaySkuUpdate = cargowaySkuList.stream().map(cargowaySkuDO -> {

            WeightVO weightVO = weightMap.get(cargowaySkuDO.getCargowayNo());
            if (Objects.isNull(weightVO)) {
                log.warn("该货道没有上传重力 {} {}", openCloseWeightVO.getDeviceId(), cargowaySkuDO.getCargowayNo());
                return null;
            }
            QtyVO qtyVO = qtyMap.get(cargowaySkuDO.getCargowayNo());
            setCargowaySku(cargowaySkuDO, weightVO, qtyVO);
            cargowaySkuDO.setModifier(openCloseWeightVO.getOperatorInfo());
            return cargowaySkuDO;
        }).filter(Objects::nonNull).collect(Collectors.toList());

        batchUpdate(cargowaySkuUpdate);
    }

    public void setCargowaySku(CargowaySkuDTO cargowaySkuDO, WeightVO weightVO, QtyVO qtyVO) {
        cargowaySkuDO.setWeight(weightVO.getWeight());
        Integer inventory = cargowaySkuDO.getInventory() != null ? cargowaySkuDO.getInventory() : 0;
        Integer qty = 0;
        if (qtyVO != null) {
            qty = qtyVO.getQty();
            //无重力补货重量是0，所以数量也是累加的
            qty = qtyVO.getWeight() < 0 ? qty * -1 : qty;
        }
        cargowaySkuDO.setInventory(Math.max(qty + inventory, 0));

    }

    public List<AndroidCargowayVO> getElectronicTag(AndroidCargowayDTO req) {
        // 获取设备信息
        List<DeviceDO> devices = deviceService.getDevicesByImei(req.getImei());
        // 获取货道信息
        List<Long> deceiveIds = devices.stream().map(DeviceDO::getId).collect(Collectors.toList());
        List<CargowayDO> cargoways = cargowayService.getCargowayList(deceiveIds);
        // 获取货道商品信息
        List<CargowaySkuDO> cargowaySkuList = service.getDeviceSkuList(deceiveIds);
        if (CollectionUtils.isEmpty(devices) || CollectionUtils.isEmpty(cargoways) || CollectionUtils.isEmpty(cargowaySkuList)) {
            return Collections.emptyList();
        }
        // 获取客户物料信息
        Map<String, CustomerItemDTO> map = Maps.newHashMap();

        return getCarList(cargoways, cargowaySkuList, devices, map);
    }

    private List<AndroidCargowayVO> getCarList(List<CargowayDO> cargowayList,
                                               List<CargowaySkuDO> cargowaySkuList,
                                               List<DeviceDO> deviceList, Map<String, CustomerItemDTO> map) {
        List<AndroidCargowayVO> list = Lists.newArrayList();
        deviceList.forEach(deviceDO -> {
            AndroidCargowayVO androidCargowayVO = new AndroidCargowayVO();
            Long deceiveId = deviceDO.getId();
            androidCargowayVO.setDeceiveId(deceiveId);
            androidCargowayVO.setCtrlBoardNo(deviceDO.getCtrlBoardNo());
            Map<Long, List<CargowayDO>> cargowayMap = cargowayList.stream()
                    .collect(Collectors.groupingBy(CargowayDO::getDeviceId));
            Map<Long, CargowaySkuDO> csMap = new HashMap<>();
            if (!CollectionUtils.isEmpty(cargowaySkuList)) {
                cargowaySkuList.forEach(f -> csMap.put(f.getCargowayId(), f));
            }
            List<AndroidCargowayVO.CargowayVO> cargowayVOs = Lists.newArrayList();
            cargowayMap.get(deceiveId).forEach(cargowayDO -> {
                AndroidCargowayVO.CargowayVO cargowayVO = converter.carDo2CarVo(cargowayDO, csMap.get(cargowayDO.getId()));
                if (!map.isEmpty() && null != map.get(cargowayVO.getSkuCode())) {
                    cargowayVO.setCustomerSkuCode(map.get(cargowayVO.getSkuCode()).getCustomerItemCode());
                    cargowayVO.setCustomerSkuName(map.get(cargowayVO.getSkuCode()).getCustomerItemName());
                }
                cargowayVOs.add(cargowayVO);
            });
            androidCargowayVO.setCargowayVOs(cargowayVOs);
            list.add(androidCargowayVO);
        });
        return list;
    }


    public List<CargowaySkuDO> getCargowaySkuByDeviceId(List<String> skuCodes, Long deviceId) {
        return this.service.getCargowaySkuByDeviceId(skuCodes, deviceId);

    }

    public void getSkuInventory(List<CargowaySkuDO> cargowaySkuList, List<UserRoleSkuDTO> userRoleSkuDo, Long deviceId) {
        Map<String, List<CargowaySkuDO>> collect = cargowaySkuList.stream().collect(Collectors.groupingBy(CargowaySkuDO::getSkuCode));

        //查询货道信息
        Map<Integer, CargowayDO> cargowayMap = cargowayService.getCargowayList(Collections.singletonList(deviceId)).stream().collect(Collectors.toMap(CargowayDO::getCargowayNo, cargowayDO -> cargowayDO));
        for (UserRoleSkuDTO userRoleSkuDTO : userRoleSkuDo) {

            //可领状态  set领用货道
            if (userRoleSkuDTO.getPickStatus().equals(PickStatusEnum.PICKUP_SUCCESS.getCode())) {
                List<CargowaySkuDO> cargowaySkuDOS = collect.get(userRoleSkuDTO.getSkuCode()).stream().sorted(Comparator.comparing(CargowaySkuDO::getInventory)).collect(Collectors.toList());
                int inventorySum = 0;
                List<UserRoleSkuDTO.CargowayInfoDTO> objects = new ArrayList<>();
                //返回 可正常领用的货道信息
                for (CargowaySkuDO cargowaySkuDO1 : cargowaySkuDOS) {
                    Integer inventory = cargowaySkuDO1.getInventory();
                    CargowayDO cargowayInfo = cargowayMap.get(cargowaySkuDO1.getCargowayNo());
                    UserRoleSkuDTO.CargowayInfoDTO cargowayInfoDTO = new UserRoleSkuDTO.CargowayInfoDTO();
                    cargowayInfoDTO.setCargowayNo(cargowaySkuDO1.getCargowayNo());
                    cargowayInfoDTO.setNum(inventory);
                    cargowayInfoDTO.setLineNum(cargowayInfo.getLineNum());
                    inventorySum += inventory;
                    objects.add(cargowayInfoDTO);
                    if (inventorySum >= userRoleSkuDTO.getPickUpByInventory()) {
                        break;
                    }
                }
                userRoleSkuDTO.setCargowayInfoList(objects);
            }
        }

    }
}

